package com.xbongbong.paas.lowcode.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.abstracts.AbstractLowCodeExecuteService;
import com.xbongbong.paas.abstracts.AbstractLowCodeHandlerFieldService;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.factory.LowCodeHandlerFieldFactory;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.FormDataHelp;
import com.xbongbong.sys.help.PackageHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.model.LowCodeServiceInfoModel;
import com.xbongbong.paas.pojo.vo.UserAndDepartmentGetVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.pro.domain.entity.LowCodeServiceInfoEntity;
import com.xbongbong.pro.domain.entity.PaasFormServiceEntity;
import com.xbongbong.pro.enums.PackageTypeEnum;
import com.xbongbong.pro.enums.businessrule.enums.RuleValueTypeEnum;
import com.xbongbong.pro.enums.lowcode.LowCodeExecuteServiceEnum;
import com.xbongbong.pro.formservice.pojo.ParamValuePojo;
import com.xbongbong.pro.lowcodeexecute.pojo.LowCodeExecuteServicePojo;
import com.xbongbong.pro.lowcodeexecute.pojo.dto.LowCodeExecuteServiceDTO;
import com.xbongbong.pro.packageInfo.pojo.vo.BasePackageInfoVO;
import com.xbongbong.saas.constant.StringConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author 吴峰
 * @date 2021/03/18 10:43
 */
@Service("lowCodeServiceExecuteServiceImpl")
public class LowCodeServiceExecuteServiceImpl extends AbstractLowCodeExecuteService {

    private static final Logger LOGGER = LoggerFactory.getLogger(LowCodeServiceExecuteServiceImpl.class);

    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private FormDataHelp formDataHelp;
    @Resource
    private LowCodeServiceInfoModel lowCodeServiceInfoModel;
    @Resource
    private PackageHelp packageHelp;


    @Override
    @Async(value = "lowCodeServiceExecuteThreadPool")
    public void execute(LowCodeExecuteServiceDTO lowCodeExecuteServiceDTO) throws XbbException {
        String corpid = lowCodeExecuteServiceDTO.getCorpid();
        BasePackageInfoVO basePackageInfoVO = packageHelp.getBasePackageInfoFromRedis(corpid);
        if (!Objects.equals(PackageTypeEnum.ULTIMATE.getType(), basePackageInfoVO.getFeeType())) {
            LOGGER.info("LowCodeServiceExecuteServiceImpl.execute no permission");
            return ;
        }
        Integer businessType = lowCodeExecuteServiceDTO.getBusinessType();
        Long formId = lowCodeExecuteServiceDTO.getFormId();
        // 获取当前表单的服务
        LowCodeExecuteServiceEnum lowCodeExecuteServiceEnum = LowCodeExecuteServiceEnum.get(lowCodeExecuteServiceDTO.getAlias());
        if (Objects.isNull(lowCodeExecuteServiceEnum)) {
            LOGGER.error("lowCode Service Info alias is Null：alias="+lowCodeExecuteServiceDTO.getAlias());
            return;
        }
        List<PaasFormServiceEntity> serviceList = getServiceList(corpid, formId, businessType, lowCodeExecuteServiceEnum);
        if (CollectionsUtil.isEmpty(serviceList)) {
            return;
        }
        PaasFormExplainEntity paasFormExplainEntity = proFormHelp.getExplainEntity(corpid, formId, businessType);
        if (Objects.isNull(paasFormExplainEntity)) {
            LOGGER.error("formExplain is Null：formId = "+lowCodeExecuteServiceDTO.getAlias()+ "；businessType=" + businessType);
            return;
        }
        List<FieldAttrEntity> fieldList = JSON.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
        Map<String, FieldAttrEntity> explainMap = new HashMap<>(fieldList.size());
        fieldList.forEach(item->{
            explainMap.put(item.getAttr(), item);
        });
        List<PaasFormDataEntityExt> dataList = lowCodeExecuteServiceDTO.getList();
        if (CollectionsUtil.isEmpty(dataList)) {
            dataList = formDataHelp.getByDataIdList(new HashSet<>(lowCodeExecuteServiceDTO.getDataId()),  businessType,  lowCodeExecuteServiceDTO.getSaasMark(),formId, corpid);
        }
        if (CollectionsUtil.isEmpty(dataList)) {
            LOGGER.info("LowCodeServiceExecuteServiceImpl.execute dataList is Empty，" + lowCodeExecuteServiceDTO.getDataId() + "， corpid = " + corpid + "， saasMark = "
                    + lowCodeExecuteServiceDTO.getSaasMark() + "， businessType=" + lowCodeExecuteServiceDTO.getBusinessType());
            return;
        }
        Set<String> userAndDeptFieldList = new HashSet<>();
        // 获取服务id和用户和部门的字段
        Set<Long> serviceIdList = getServiceIdList(userAndDeptFieldList, serviceList, explainMap, lowCodeExecuteServiceEnum);
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        param.put(StringConstant.IDIN, serviceIdList);
        List<LowCodeServiceInfoEntity> lowCodeServiceInfoList = lowCodeServiceInfoModel.findEntitys(param);
        Map<Long, LowCodeServiceInfoEntity> lowCodeServiceInfoEntityMap = new HashMap<>(lowCodeServiceInfoList.size());
        lowCodeServiceInfoList.forEach(item->{
            lowCodeServiceInfoEntityMap.put(item.getId(), item);
        });
        UserAndDepartmentGetVO userAndDepartmentGetVO = getUserAndDepartment(userAndDeptFieldList, dataList, explainMap, corpid);

        LowCodeExecuteServicePojo lowCodeExecuteServicePojo = new LowCodeExecuteServicePojo(businessType, lowCodeExecuteServiceDTO.getSaasMark(), corpid, formId, explainMap, userAndDepartmentGetVO);
        for (PaasFormDataEntityExt dataEntityExt : dataList) {
            for (PaasFormServiceEntity service : serviceList) {
                JSONObject paramValue = new JSONObject();
                List<ParamValuePojo> list = new ArrayList<>();
                switch (lowCodeExecuteServiceEnum) {
                    case ADD:
                        list = JSON.parseArray(service.getCommitServiceParam(), ParamValuePojo.class);
                        break;
                    case EDIT:
                        list = JSON.parseArray(service.getEditServiceParam(), ParamValuePojo.class);
                        break;
                    case DELETE:
                        list = JSON.parseArray(service.getDeleteServiceParam(), ParamValuePojo.class);
                        break;
                    default:
                        break;
                }
                for (ParamValuePojo paramValuePojo : list) {
                    if (Objects.equals(RuleValueTypeEnum.DYNAMIC_VALUE.getType(), paramValuePojo.getValueType())) {

                        FieldAttrEntity fieldAttrEntity = explainMap.get(paramValuePojo.getValueAttr());
                        AbstractLowCodeHandlerFieldService lowCodeHandlerFieldService = LowCodeHandlerFieldFactory.getServiceExecute(fieldAttrEntity.getFieldType());
                        Object value = lowCodeHandlerFieldService.handlerField(fieldAttrEntity, dataEntityExt.getData(), lowCodeExecuteServicePojo);
                        paramValue.put(paramValuePojo.getParameter(), value);
                    } else {
                        paramValue.put(paramValuePojo.getParameter(), paramValuePojo.getValue());
                    }
                }
                Long serviceId = null;
                switch (lowCodeExecuteServiceEnum) {
                    case ADD:
                        serviceId = service.getCommitServiceId();
                        break;
                    case EDIT:
                        serviceId = service.getEditServiceId();
                        break;
                    case DELETE:
                        serviceId = service.getDeleteServiceId();
                        break;
                        default:
                            break;
                }
                LowCodeServiceInfoEntity lowCodeServiceInfoEntity = lowCodeServiceInfoEntityMap.get(serviceId);
                if (Objects.isNull(lowCodeServiceInfoEntity)) {
                    LOGGER.error("lowCode Service Info is Null：serviceId="+serviceId);
                    return;
                }
                send(lowCodeServiceInfoEntity, paramValue);
            }
        }


    }
}
